package role

import (
	"errors"

	"gorm.io/gorm"
)

// Service 角色业务逻辑层接口
type Service interface {
	Create(req *CreateRequest) (*RoleWithPermissions, error)
	GetByID(id uint) (*RoleWithPermissions, error)
	Update(id uint, req *UpdateRequest) (*RoleWithPermissions, error)
	Delete(id uint) error
	List(req *QueryRequest) ([]*RoleWithPermissions, int64, error)
	AssignPermissions(id uint, req *AssignPermissionsRequest) (*RoleWithPermissions, error)
	GetAllRoles() ([]*Role, error)
}

// service 角色业务逻辑层实现
type service struct {
	repo Repository
}

// NewService 创建角色业务逻辑层
func NewService(repo Repository) Service {
	return &service{
		repo: repo,
	}
}

// Create 创建角色
func (s *service) Create(req *CreateRequest) (*RoleWithPermissions, error) {
	// 检查角色名是否已存在
	if _, err := s.repo.GetByName(req.Name); err == nil {
		return nil, errors.New("角色名已存在")
	}

	// 检查角色代码是否已存在
	if _, err := s.repo.GetByCode(req.Code); err == nil {
		return nil, errors.New("角色代码已存在")
	}

	// 设置默认状态
	status := 1
	if req.Status != nil {
		status = *req.Status
	}

	// 设置默认显示名称
	displayName := req.DisplayName
	if displayName == "" {
		displayName = req.Name
	}

	role := &Role{
		Name:        req.Name,
		Code:        req.Code,
		DisplayName: displayName,
		Description: req.Description,
		Status:      status,
	}

	// 创建角色
	if err := s.repo.Create(role); err != nil {
		return nil, err
	}

	// 分配权限
	if len(req.PermissionIDs) > 0 {
		if err := s.repo.UpdatePermissions(role.ID, req.PermissionIDs); err != nil {
			return nil, errors.New("权限分配失败")
		}
	}

	// 返回带权限信息的角色
	return s.repo.GetRoleWithPermissions(role.ID)
}

// GetByID 根据ID获取角色
func (s *service) GetByID(id uint) (*RoleWithPermissions, error) {
	role, err := s.repo.GetRoleWithPermissions(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("角色不存在")
		}
		return nil, err
	}
	return role, nil
}

// Update 更新角色
func (s *service) Update(id uint, req *UpdateRequest) (*RoleWithPermissions, error) {
	role, err := s.repo.GetByIDWithoutPermissions(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("角色不存在")
		}
		return nil, err
	}

	// 更新字段
	if req.Name != nil {
		// 检查角色名是否已被其他角色使用
		if existingRole, err := s.repo.GetByName(*req.Name); err == nil && existingRole.ID != id {
			return nil, errors.New("角色名已存在")
		}
		role.Name = *req.Name
	}

	if req.Code != nil {
		// 检查角色代码是否已被其他角色使用
		if existingRole, err := s.repo.GetByCode(*req.Code); err == nil && existingRole.ID != id {
			return nil, errors.New("角色代码已存在")
		}
		role.Code = *req.Code
	}

	if req.DisplayName != nil {
		if *req.DisplayName == "" {
			// 如果显示名称为空，使用角色名称
			role.DisplayName = role.Name
		} else {
			role.DisplayName = *req.DisplayName
		}
	}

	if req.Description != nil {
		role.Description = *req.Description
	}

	if req.Status != nil {
		role.Status = *req.Status
	}

	// 更新角色信息
	if err := s.repo.Update(role); err != nil {
		return nil, err
	}

	// 更新权限
	if req.PermissionIDs != nil {
		if err := s.repo.UpdatePermissions(role.ID, req.PermissionIDs); err != nil {
			return nil, errors.New("权限更新失败")
		}
	}

	// 返回更新后的角色信息
	return s.repo.GetRoleWithPermissions(role.ID)
}

// Delete 删除角色
func (s *service) Delete(id uint) error {
	role, err := s.repo.GetByID(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("角色不存在")
		}
		return err
	}

	return s.repo.Delete(role.ID)
}

// List 获取角色列表
func (s *service) List(req *QueryRequest) ([]*RoleWithPermissions, int64, error) {
	// 设置默认分页参数
	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}
	if req.PageSize > 100 {
		req.PageSize = 100
	}

	return s.repo.List(req)
}

// AssignPermissions 分配权限
func (s *service) AssignPermissions(id uint, req *AssignPermissionsRequest) (*RoleWithPermissions, error) {
	role, err := s.repo.GetByIDWithoutPermissions(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("角色不存在")
		}
		return nil, err
	}

	// 更新权限
	if err := s.repo.UpdatePermissions(role.ID, req.PermissionIDs); err != nil {
		return nil, errors.New("权限分配失败")
	}

	// 返回更新后的角色信息
	return s.repo.GetRoleWithPermissions(role.ID)
}

// GetAllRoles 获取所有角色
func (s *service) GetAllRoles() ([]*Role, error) {
	return s.repo.GetAllRoles()
}
